package proceso;

import java.io.IOException;
import java.util.LinkedList;
import javax.xml.parsers.*;
import org.w3c.dom.Element;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;

import java.util.Iterator;



/*
 * Clase que maneja la lectura del archivo de entrada xml
 */
public class XMLParser extends DefaultHandler {

    String archivoXML;
    int numPistas;
    int numBloquesPorPista;
    LinkedList<Proceso> listaProcesos;
    String tempVal;
    Proceso tempProc;
    Peticion tempPet;

    public XMLParser(String archivoXML) {
        this.archivoXML = archivoXML;  
        this.listaProcesos = new LinkedList<Proceso>();
        parseDocumentSax();
    }

    /*
     * Parsea el documento asociado al objeto
     */
    private void parseDocumentSax() {
        SAXParserFactory spf = SAXParserFactory.newInstance();
        try {            
            SAXParser sp = spf.newSAXParser();
            sp.parse(this.archivoXML, this);
        } catch (SAXException se) {
            se.printStackTrace();
        } catch (ParserConfigurationException pce) {
            pce.printStackTrace();
        } catch (IOException ie) {
            ie.printStackTrace();
        }
    }

    /*
     * Maneja lo que se debe hacer cuando se abre un tag en la lectura del xml
     */
    @Override
    public void startElement(String uri, String localName, String qName,
            Attributes attributes) throws SAXException {

        tempVal = "";
        if (qName.equalsIgnoreCase("Process")) {
            tempProc = new Proceso();
        }
        else if(qName.equalsIgnoreCase("Operation")) {
            tempPet = new Peticion();
        }
    }

    /*
     * Maneja lo que se debe hacer en caso de lectura de texto texto
     */
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        tempVal = new String(ch, start, length);
    }

    @Override
    public void endElement(String uri, String localName,
            String qName) throws SAXException {
        
        if (qName.equalsIgnoreCase("Tracks")) {
            this.numPistas = Integer.parseInt(tempVal);
        }
        else if (qName.equalsIgnoreCase("BlocksPerTrack")) {
            this.numBloquesPorPista = Integer.parseInt(tempVal);
        }        
        else if (qName.equalsIgnoreCase("Process")) {
            listaProcesos.add(tempProc);
        }
        else if (qName.equalsIgnoreCase("Id")) {
            tempProc.setPid(Integer.parseInt(tempVal));
        }
        else if (qName.equalsIgnoreCase("Priority")) {
            String tempStr[] = new String[2];
            tempStr = tempVal.split(" ");
            if (tempStr[0].equalsIgnoreCase("RT")) {
                tempProc.setPrioridad(Integer.parseInt(tempStr[1]));
            }
            else {
                tempProc.setPrioridad(Integer.parseInt(tempStr[1]) + 7);
            }
        }    
        else if (qName.equalsIgnoreCase("Operation")) {
            tempProc.agregarPeticion(tempPet);            
        }
        else if (qName.equalsIgnoreCase("InstructionType")) {
            if (tempVal.equalsIgnoreCase("READ")) {
                tempPet.setTipo(1);
            }
            else {
                tempPet.setTipo(2);
            }  
        }
        else if (qName.equalsIgnoreCase("Block")) {
            tempPet.setBloque(Integer.parseInt(tempVal));
        }
        else if (qName.equalsIgnoreCase("ArrivalTimeReq")) {  
            tempPet.setTiempoPeticion(Integer.parseInt(tempVal));
        }

    }

    public int getNumBloquesPorPista() {
        return numBloquesPorPista;
    }

    public int getNumPistas() {
        return numPistas;
    } 
    
    
    /*
     * return la lista de los procesos que tenga el parser
     */    
    public LinkedList<Proceso> getListaProcesos() {
        return listaProcesos;
    }

    private LinkedList<Peticion> getInstructions(Element ele, String tagName) {
        return new LinkedList<Peticion>();
    }  
    
    
    @Override
    public String toString() {
        String str = "XMLParser " + archivoXML + "\n";
        str += "\tNum. Pistas: " + numPistas + "\n";
        str += "\tNum. Bloques por pistas: " + numBloquesPorPista + "\n"; 
        Iterator itr = listaProcesos.iterator();
        while (itr.hasNext()) {
            str += itr.next().toString();
        }
        return str;
    }
}
